/*
 * Copyright (c) 2009-2024 Arm Limited. All rights reserved.
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the License); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*============================ INCLUDES ======================================*/

#if defined(_RTE_)
#   include "RTE_Components.h"
#endif

#if defined(RTE_Acceleration_Arm_2D_Helper_PFB)

#include "arm_2d.h"

#ifdef RTE_Acceleration_Arm_2D_Scene1

#define __USER_SCENE1_IMPLEMENT__
#include "arm_2d_scene_1.h"
#include "arm_2d_scenes.h"
#include "arm_2d_helper.h"
#include "arm_2d_example_controls.h"

#include <stdlib.h>
#include <string.h>

#if defined(__clang__)
#   pragma clang diagnostic push
#   pragma clang diagnostic ignored "-Wunknown-warning-option"
#   pragma clang diagnostic ignored "-Wreserved-identifier"
#   pragma clang diagnostic ignored "-Wsign-conversion"
#   pragma clang diagnostic ignored "-Wpadded"
#   pragma clang diagnostic ignored "-Wcast-qual"
#   pragma clang diagnostic ignored "-Wcast-align"
#   pragma clang diagnostic ignored "-Wmissing-field-initializers"
#   pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
#   pragma clang diagnostic ignored "-Wmissing-prototypes"
#   pragma clang diagnostic ignored "-Wunused-variable"
#   pragma clang diagnostic ignored "-Wgnu-statement-expression"
#   pragma clang diagnostic ignored "-Wdeclaration-after-statement"
#   pragma clang diagnostic ignored "-Wunused-function"
#   pragma clang diagnostic ignored "-Wmissing-declarations"  
#elif __IS_COMPILER_ARM_COMPILER_5__
#   pragma diag_suppress 64,177
#elif __IS_COMPILER_IAR__
#   pragma diag_suppress=Pa089,Pe188,Pe177,Pe174
#elif __IS_COMPILER_GCC__
#   pragma GCC diagnostic push
#   pragma GCC diagnostic ignored "-Wformat="
#   pragma GCC diagnostic ignored "-Wpedantic"
#   pragma GCC diagnostic ignored "-Wunused-function"
#   pragma GCC diagnostic ignored "-Wunused-variable"
#   pragma GCC diagnostic ignored "-Wincompatible-pointer-types"
#endif

/*============================ MACROS ========================================*/

#if __GLCD_CFG_COLOUR_DEPTH__ == 8

#   define c_tileCMSISLogo          c_tileCMSISLogoGRAY8

#elif __GLCD_CFG_COLOUR_DEPTH__ == 16

#   define c_tileCMSISLogo          c_tileCMSISLogoRGB565

#elif __GLCD_CFG_COLOUR_DEPTH__ == 32

#   define c_tileCMSISLogo          c_tileCMSISLogoCCCA8888
#else
#   error Unsupported colour depth!
#endif

/*============================ MACROFIED FUNCTIONS ===========================*/
#undef this
#define this (*ptThis)

/*============================ TYPES =========================================*/
/*============================ GLOBAL VARIABLES ==============================*/
static uint16_t button_draw_time = 0;


extern uint16_t key_num ;
static void key_board_run(arm_2d_scene_t *ptScene);
/*============================ PROTOTYPES ====================================*/
/*============================ LOCAL VARIABLES ===============================*/

/*! define dirty regions */
IMPL_ARM_2D_REGION_LIST(s_tDirtyRegions, static)

    /* a dirty region to be specified at runtime*/
    ADD_REGION_TO_LIST(s_tDirtyRegions,
        0  /* initialize at runtime later */
    ),
    
    /* add the last region:
        * it is the top left corner for text display 
        */
    ADD_LAST_REGION_TO_LIST(s_tDirtyRegions,
        .tLocation = {
            .iX = 0,
            .iY = 0,
        },
        .tSize = {
            .iWidth = 320,
            .iHeight = 240,
        },
    ),

END_IMPL_ARM_2D_REGION_LIST(s_tDirtyRegions)

/*============================ IMPLEMENTATION ================================*/

static void __on_scene1_load(arm_2d_scene_t *ptScene)
{
    user_scene_1_t *ptThis = (user_scene_1_t *)ptScene;
    ARM_2D_UNUSED(ptThis);

}

static void __on_scene1_depose(arm_2d_scene_t *ptScene)
{
    user_scene_1_t *ptThis = (user_scene_1_t *)ptScene;
    ARM_2D_UNUSED(ptThis);
    
    ptScene->ptPlayer = NULL;
    
    /* reset timestamp */
    arm_foreach(int64_t,this.lTimestamp, ptItem) {
        *ptItem = 0;
    }

    if (!this.bUserAllocated) {
        __arm_2d_free_scratch_memory(ARM_2D_MEM_TYPE_UNSPECIFIED, ptScene);
    }
}

/*----------------------------------------------------------------------------*
 * Scene 1                                                                    *
 *----------------------------------------------------------------------------*/

static void __on_scene1_background_start(arm_2d_scene_t *ptScene)
{
    user_scene_1_t *ptThis = (user_scene_1_t *)ptScene;
    ARM_2D_UNUSED(ptThis);

}

static void __on_scene1_background_complete(arm_2d_scene_t *ptScene)
{
    user_scene_1_t *ptThis = (user_scene_1_t *)ptScene;
    ARM_2D_UNUSED(ptThis);

}


static void __on_scene1_frame_start(arm_2d_scene_t *ptScene)
{
    user_scene_1_t *ptThis = (user_scene_1_t *)ptScene;
    ARM_2D_UNUSED(ptThis);

}

static void __on_scene1_frame_complete(arm_2d_scene_t *ptScene)
{
    user_scene_1_t *ptThis = (user_scene_1_t *)ptScene;
    ARM_2D_UNUSED(ptThis);
     key_board_run(ptScene);
    /* switch to next scene after 3s */
    if (arm_2d_helper_is_time_out(1000, &this.lTimestamp[0])) {
        //arm_2d_scene_player_switch_to_next_scene(ptScene->ptPlayer);
			  button_draw_time++;
    }
}

static void __before_scene1_switching_out(arm_2d_scene_t *ptScene)
{
    user_scene_1_t *ptThis = (user_scene_1_t *)ptScene;
    ARM_2D_UNUSED(ptThis);

}

static void draw_my_catalogue_list(void *pTarget,                                  
                 const arm_2d_tile_t *ptTile,                   
                 arm_2d_region_t Region,
								 bool bIsNewFrame){
									 
		draw_round_corner_box(  ptTile, 
                                    &Region, 
                                    GLCD_COLOR_WHITE, 
                                    255,
                                    bIsNewFrame);
            
            
            
		draw_round_corner_border(   ptTile, 
																&Region, 
																GLCD_COLOR_BLACK, 
																(arm_2d_border_opacity_t)
																		{32, 32, 255-64, 255-64},
																(arm_2d_corner_opacity_t)
																		{0, 128, 128, 128});								 
									 
}

static void draw_my_catalogue(void *pTarget,                                  
                 const arm_2d_tile_t *ptTile,                   
                 bool bIsNewFrame){
		arm_2d_region_t myRegion;
		char my_time = 0;							 
		uint16_t i;							 
		myRegion.tLocation.iX = 10;
		myRegion.tLocation.iY	 = 120;
		myRegion.tSize.iHeight = 40;
		myRegion.tSize.iWidth = 60;	
		do{	
				my_time = button_draw_time & 0x07;	
		    draw_my_catalogue_list(pTarget,  ptTile, myRegion,bIsNewFrame);
				myRegion.tLocation.iX = 11 + 5*my_time;
				myRegion.tLocation.iY = 140;
				myRegion.tSize.iHeight = 5;
				myRegion.tSize.iWidth = 20;	
		    arm_2d_fill_colour_with_opacity(   
                ptTile, 
                &myRegion, 
                (__arm_2d_color_t){GLCD_COLOR_BLACK},
                200);			
			
		}while(0);

		myRegion.tLocation.iX = 80+10;	
		myRegion.tLocation.iY	 = 120;
		myRegion.tSize.iHeight = 40;
		myRegion.tSize.iWidth = 60;	
		do{
		    draw_my_catalogue_list(pTarget,  ptTile, myRegion,bIsNewFrame);
				myRegion.tLocation.iX = 93 ;
				myRegion.tLocation.iY = 152;
				myRegion.tSize.iHeight = 5;
				myRegion.tSize.iWidth = 20;	
		    arm_2d_fill_colour_with_opacity(   
                ptTile, 
                &myRegion, 
                (__arm_2d_color_t){GLCD_COLOR_BLACK},
                200);	
				myRegion.tLocation.iX = 93+25 ;
				myRegion.tLocation.iY = 152;
				myRegion.tSize.iHeight = 5;
				myRegion.tSize.iWidth = 54-25;	
		    arm_2d_fill_colour_with_opacity(   
                ptTile, 
                &myRegion, 
                (__arm_2d_color_t){GLCD_COLOR_BLACK},
                200);	
				myRegion.tLocation.iX = 93+20 ;
				myRegion.tLocation.iY = 152-25 + 4+ 3*my_time;
				myRegion.tSize.iHeight = 5;
				myRegion.tSize.iWidth = 5;	
		    arm_2d_fill_colour_with_opacity(   
                ptTile, 
                &myRegion, 
                (__arm_2d_color_t){GLCD_COLOR_BLACK},
                200);		
				myRegion.tLocation.iX = 93+15 ;
				myRegion.tLocation.iY = 152-30 + 4 + 3*my_time;
				myRegion.tSize.iHeight = 5;
				myRegion.tSize.iWidth = 15;	
		    arm_2d_fill_colour_with_opacity(   
                ptTile, 
                &myRegion, 
                (__arm_2d_color_t){GLCD_COLOR_BLACK},
                200);						
        			
		}while(0);			

		myRegion.tLocation.iX = 160+10;
    myRegion.tLocation.iY	 = 120;
		myRegion.tSize.iHeight = 40;
		myRegion.tSize.iWidth = 60;			
		draw_my_catalogue_list(pTarget,  ptTile, myRegion,bIsNewFrame);	

		myRegion.tLocation.iX = 240+10;	
    myRegion.tLocation.iY	 = 120;
		myRegion.tSize.iHeight = 40;
		myRegion.tSize.iWidth = 60;			
		draw_my_catalogue_list(pTarget,  ptTile, myRegion,bIsNewFrame);													
									 
}

static
IMPL_PFB_ON_DRAW(__pfb_draw_scene1_handler)
{
    user_scene_1_t *ptThis = (user_scene_1_t *)pTarget;
    arm_2d_size_t tScreenSize = ptTile->tRegion.tSize;

    ARM_2D_UNUSED(ptTile);
    ARM_2D_UNUSED(bIsNewFrame);
    ARM_2D_UNUSED(tScreenSize);
    
    arm_2d_canvas(ptTile, __top_canvas) {
    /*-----------------------draw the foreground begin-----------------------*/
        
        /* following code is just a demo, you can remove them */
        
        arm_2d_fill_colour(ptTile, NULL, GLCD_COLOR_BLUE);
			
			draw_my_catalogue( pTarget,                                  
                 ptTile,                   
                  bIsNewFrame);

        




        /* draw text at the top-left corner */

        arm_lcd_text_set_target_framebuffer((arm_2d_tile_t *)ptTile);
        arm_lcd_text_set_font(&ARM_2D_FONT_6x8.use_as__arm_2d_font_t);
        arm_lcd_text_set_draw_region(NULL);
        arm_lcd_text_set_colour(GLCD_COLOR_RED, GLCD_COLOR_WHITE);
        arm_lcd_text_location(0,0);
        //arm_lcd_puts("Scene 1");
				arm_lcd_printf("Scene %d",key_num);

    /*-----------------------draw the foreground end  -----------------------*/
    }
    arm_2d_op_wait_async(NULL);

    return arm_fsm_rt_cpl;
}

ARM_NONNULL(1)
user_scene_1_t *__arm_2d_scene1_init(   arm_2d_scene_player_t *ptDispAdapter, 
                                        user_scene_1_t *ptThis)
{
    bool bUserAllocated = false;
    assert(NULL != ptDispAdapter);

    s_tDirtyRegions[dimof(s_tDirtyRegions)-1].ptNext = NULL;

    /* get the screen region */
    arm_2d_region_t tScreen
        = arm_2d_helper_pfb_get_display_area(
            &ptDispAdapter->use_as__arm_2d_helper_pfb_t);

    /* initialise dirty region 0 at runtime
     * this demo shows that we create a region in the centre of a screen(320*240)
     * for a image stored in the tile c_tileCMSISLogoMask
     */
    //arm_2d_align_centre(tScreen, c_tileCMSISLogoMask.tRegion.tSize) {
        //s_tDirtyRegions[0].tRegion = __centre_region;
    //}

    //s_tDirtyRegions[dimof(s_tDirtyRegions)-1].tRegion.tSize.iWidth 
    //                                                    = tScreen.tSize.iWidth;
    
    if (NULL == ptThis) {
        ptThis = (user_scene_1_t *)
                    __arm_2d_allocate_scratch_memory(   sizeof(user_scene_1_t),
                                                        __alignof__(user_scene_1_t),
                                                        ARM_2D_MEM_TYPE_UNSPECIFIED);
        assert(NULL != ptThis);
        if (NULL == ptThis) {
            return NULL;
        }
    } else {
        bUserAllocated = true;
    }
    memset(ptThis, 0, sizeof(user_scene_1_t));

    *ptThis = (user_scene_1_t){
        .use_as__arm_2d_scene_t = {

            /* the canvas colour */
            .tCanvas = {GLCD_COLOR_WHITE}, 

            /* Please uncommon the callbacks if you need them
             */
            .fnOnLoad       = &__on_scene1_load,
            .fnScene        = &__pfb_draw_scene1_handler,
            .ptDirtyRegion  = (arm_2d_region_list_item_t *)s_tDirtyRegions,
            

            //.fnOnBGStart    = &__on_scene1_background_start,
            //.fnOnBGComplete = &__on_scene1_background_complete,
            .fnOnFrameStart = &__on_scene1_frame_start,
            //.fnBeforeSwitchOut = &__before_scene1_switching_out,
            .fnOnFrameCPL   = &__on_scene1_frame_complete,
            .fnDepose       = &__on_scene1_depose,

            .bUseDirtyRegionHelper = false,
        },
        .bUserAllocated = bUserAllocated,
    };

    /* ------------   initialize members of user_scene_1_t begin ---------------*/


    /* ------------   initialize members of user_scene_1_t end   ---------------*/

    arm_2d_scene_player_append_scenes(  ptDispAdapter, 
                                        &this.use_as__arm_2d_scene_t, 
                                        1);

    return ptThis;
}

//===========================================================================
static void key_board_run(arm_2d_scene_t *ptScene){
		switch(key_num){
			case 13:
					__arm_2d_scene0_init(   &DISP0_ADAPTER ,NULL);
					arm_2d_scene_player_switch_to_next_scene(ptScene->ptPlayer);
			break;
			case 14:
					__arm_2d_scene2_init(   &DISP0_ADAPTER ,NULL);
					arm_2d_scene_player_switch_to_next_scene(ptScene->ptPlayer);
			break;
		}
}






#if defined(__clang__)
#   pragma clang diagnostic pop
#endif

#endif

#endif

